
// for shared_ptr weak_ptr
#include <memory>
// for function bind
#include <functional>
#include <iostream>
#include <vector>
#include <cstdint> // for uint64_t
#include <unordered_map>
#include <unistd.h>


using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask{
private:
    uint64_t _id;           // 定时器（任务） ID
    uint32_t _timeout;      // 定时器超时时间
    TaskFunc _task;         // 定时器的回调任务
    bool _canceled;          // 是否被取消

    ReleaseFunc _release;   // 删除 TimerWheel 中保存的定时器对象信息
    /* 既然 TimerTask 最清楚自己什么时候要死，那么最自然的办法是：
    在它析构时调用一个回调函数 _release，这个回调专门去清理 _timers。*/ 

public:
    TimerTask(uint64_t id, uint32_t timeout, const TaskFunc& task) : _id(id), _timeout(timeout), _task(task), _canceled(false)  //, _release(release)
    {}

    ~TimerTask() {
        if(_canceled == false) { _task();}
        _release(); //清理 TimeWheel 的 _timers
    }
    void Cancel(){
        _canceled = true;
    }
    void SetRelease(const ReleaseFunc& release_cb){
        _release = release_cb;
    }
    uint32_t DelayTime() {return _timeout;}
};

// 时间轮
class TimerWheel{
private:
    using PtrTask = std::shared_ptr<TimerTask>;
    using WeakTask = std::weak_ptr<TimerTask>;    
    int _tick;                                      // 当前时间指针，指到哪就销毁哪
    int _capacity;                                  // 表盘最大数量——最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;       // 依赖 _capacity 放到下面
    std::unordered_map<uint64_t, WeakTask> _timers;
private:
    void RemoveTimer(uint64_t id){
        auto it = _timers.find(id);
        if(it != _timers.end()){
            _timers.erase(it);
        }
    }
public:
    TimerWheel(): _capacity(60), _wheel(_capacity), _tick(0) {}
    ~TimerWheel(){}
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc& cb){
        PtrTask pt(new TimerTask(id, delay, cb));
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
        int pos = (_tick + delay) % _capacity; 
        _wheel[pos].push_back(pt);
        _timers[id] = WeakTask(pt);
    }
    void TimerRefresh(uint64_t id){
        auto it = _timers.find(id);
        if(it == _timers.end()) return;

        PtrTask pt = it->second.lock(); // 延长 由 weakptr 指向的 ptr 的生命——即再生成一个 shared_ptr 锁住对象的存活
        int delay = pt->DelayTime();
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
    }
    void TimerCancel(uint64_t id){
        auto it = _timers.find(id);
        if(it == _timers.end()) return;

        PtrTask pt = it->second.lock();
        if(pt) pt->Cancel();
    }
    // 这个函数应该每一秒被执行一次
    void RunTimerTask(){
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();      // 清空该处的 PtrTask 调用定时器析构
    }
};




struct Test{
public:
    Test(){
        std::cout << "构造" << std::endl;
    }
    ~Test(){
        std::cout << "析构" << std::endl;
    }
};

void Del(Test* t){
    delete t;
}

int main(){
    TimerWheel tw;
    Test *t = new Test();

    tw.TimerAdd(888, 3, std::bind(Del, t));
    for(int i = 0; i < 5; ++i){
        sleep(1);
        tw.TimerRefresh(888);
        tw.RunTimerTask();  //时间开始
        std::cout << "刷新了一下\n";
    }
    tw.TimerCancel(888);
    while(1){
        std::cout << "--------------\n";
        sleep(1);
        tw.RunTimerTask();
    }

    return 0;
}